import 'dart:io';

import 'package:dio/dio.dart';
import 'package:smart_devices/constant/api.dart';
import 'package:smart_devices/model/api_response.dart';
import 'package:smart_devices/service/shared_preference.dart';

import 'loading.dart';
import 'log.dart';

class HttpClientInterceptor extends Interceptor {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    Loading.show(text: '加载中...');
    Map<String, dynamic> headers = options.headers;
    if (headers[HttpHeaders.contentTypeHeader] != null) {
      headers[HttpHeaders.contentTypeHeader] = ContentType.json.mimeType;
    }
    String token = SharedPreferenceService.to.getString(SharedPreferenceService.token);
    if (token.isNotEmpty) {
      headers['token'] = token;
    }
    headers['x-client'] = _xClient();
    super.onRequest(options, handler);
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    Loading.dismiss();
    if (response.statusCode == HttpStatus.ok) {
      Map<String, dynamic> jsonMap = response.data;
      ApiResponse data = ApiResponse.fromJson(jsonMap);
      if (data.code != 0) {
        return handler.reject(DioException(
            requestOptions: response.requestOptions,
            response: response,
            message: data.message,
            error: data.message));
      }
    }
    super.onResponse(response, handler);
  }

  @override
  void onError(DioException err, ErrorInterceptorHandler handler) {
    Loading.dismiss();
    try {
      var code = err.response?.statusCode;
      if (code == HttpStatus.internalServerError) {
        List<String>? type = err.response?.headers[HttpHeaders.contentTypeHeader];
        if (type != null &&
            (type.contains('application/json') ||
                type.contains('application/json;charset=utf-8'))) {
          ApiResponse a = ApiResponse.fromJson(err.response?.data);
          if (a.message != null && a.message!.isNotEmpty) {
            Loading.showError(a.message!);
          }
          return super.onError(
              DioException(
                  requestOptions: err.requestOptions, response: err.response, error: a.message),
              handler);
        }
      }
    } catch (e) {
      LogUtils.e(e);
    }
    super.onError(err, handler);
  }

  String _xClient() {
    String xClient = 'flutter';
    if (Platform.isAndroid) {
      xClient = 'android';
    } else if (Platform.isIOS) {
      xClient = 'ios';
    }
    return xClient;
  }
}

class HttpClientUtils {
  static final HttpClientUtils instance = HttpClientUtils._internal();

  factory HttpClientUtils() {
    return instance;
  }

  HttpClientUtils._internal() {
    BaseOptions options = BaseOptions(
        baseUrl: ApiUrl.baseUrl,
        connectTimeout: const Duration(seconds: 30),
        sendTimeout: const Duration(seconds: 30),
        receiveTimeout: const Duration(seconds: 30),
        validateStatus: (code) {
          ///指定这些HttpCode都算成功
          List<int> codes = [200];
          if (codes.contains(code)) {
            return true;
          } else {
            return false;
          }
        });

    ///初始化
    _dio = Dio(options);
    _dio.interceptors.add(HttpClientInterceptor());
  }

  late Dio _dio;

  get dio {
    return _dio;
  }

  Future<ApiResponse> httpPost(String path, {dynamic data}) async {
    Response<dynamic> response = await _dio.post(path, data: data);
    return ApiResponse.fromJson(response.data);
  }

  Future<ApiResponse> httpGet(String path, {Map<String, dynamic>? params}) async {
    Response<dynamic> response = await _dio.get(path, queryParameters: params);
    return ApiResponse.fromJson(response.data);
  }

  ///   附件上传
  ///   FormData.fromMap({
  ///     "name": "wendux",
  ///    "age": 25,
  ///    "file": await MultipartFile.fromFile("./text.txt",filename: "upload.txt"),
  ///    "files": [
  ///       await MultipartFile.fromFile("./text1.txt", filename: "text1.txt"),
  ///       await MultipartFile.fromFile("./text2.txt", filename: "text2.txt"),
  ///     ]
  ///    })
  ///    response = await dio.post("/upload", data: formData)

  Future<ApiResponse> upload(String path, FormData data) async {
    Response<dynamic> response = await _dio.post(path, data: data, options: _uploadFile());
    return ApiResponse.fromJson(response.data);
  }

  Options _postJsonOptions(bool needToken) {
    Map<String, String> header = <String, String>{};
    header['x-client'] = _xClient();
    if (needToken) {
      header['token'] = '';
    }
    return Options(
        method: 'POST',
        headers: header,
        contentType: ContentType.json.mimeType,
        responseType: ResponseType.json);
  }

  String _xClient() {
    String xClient = 'flutter';
    if (Platform.isAndroid) {
      xClient = 'android';
    } else if (Platform.isIOS) {
      xClient = 'ios';
    }
    return xClient;
  }

  Options _getJsonOptions(bool needToken) {
    Map<String, String> header = <String, String>{};
    header['x-client'] = _xClient();
    if (needToken) {
      header['token'] = '';
    }
    return Options(
        method: 'GET',
        headers: header,
        contentType: ContentType.json.mimeType,
        responseType: ResponseType.json);
  }

  Options _uploadFile() {
    Map<String, dynamic> headers = {};
    return Options(
        method: 'POST',
        headers: headers,
        contentType: Headers.multipartFormDataContentType,
        responseType: ResponseType.json);
  }
}
